package com.frank.loadinglibrary.common;

import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.Rect;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author SUQI
 * @date 2021/5/8
 * @description 九宫格变换动画
 **/
public class CubeGridComponent extends BaseLoadingComponent<CubeGridComponent> implements Component.DrawTask {

    private int num = 9;
    private float[] radius = new float[num];
    private int[] delays = new int[]{
            200, 100, 0,
            300, 200, 100,
            400, 300, 200
    };
    private Paint mPaint;
    private ScheduledExecutorService service = Executors.newScheduledThreadPool(num);
    private EventHandler handler;

    public CubeGridComponent(Context context) {
        this(context, null);
    }

    public CubeGridComponent(Context context, AttrSet attrSet) {
        this(context, attrSet, null);
    }

    public CubeGridComponent(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        initPaint();
        addDrawTask(this);
        handler = new CubeGridHandler(EventRunner.getMainEventRunner());
        startAnimators();
    }

    private void initPaint() {
        mPaint = new Paint();
        mPaint.setColor(Color.WHITE);
        mPaint.setAntiAlias(true);
    }

    @Override
    protected void stopAnimators() {
        if (service != null) {
            if (!service.isShutdown()) {
                service.shutdown();
            }
        }
    }

    @Override
    protected void startAnimators() {
        for (int i = 0; i < num; i++) {
            service.scheduleWithFixedDelay(new CubeGridRunnable(i), delays[i], 25, TimeUnit.MILLISECONDS);
        }
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        if (getRect() != null) {
            Rect bounds = clipSquare(getRect(), 50);
            int width = (int) (bounds.getWidth() * 0.33f);
            int height = (int) (bounds.getHeight() * 0.33f);
            for (int i = 0; i < num; i++) {
                int x = i % 3;
                int y = i / 3;
                int l = bounds.left + x * width;
                int t = bounds.top + y * height;
                RectFloat max = new RectFloat(l, t, l + width, t + width);
                float r = max.getWidth() / 2f * radius[i];

                RectFloat now = new RectFloat(
                        max.getVerticalCenter() - r,
                        max.getHorizontalCenter() - r,
                        max.getVerticalCenter() + r,
                        max.getHorizontalCenter() + r
                );

                canvas.drawRect(now, mPaint);
            }
        }
    }

    private Rect getRect() {
        return new Rect(0, 0, getWidth(), getHeight());
    }

    public Rect clipSquare(Rect rect, int bound) {
        int w = rect.getWidth();
        int h = rect.getHeight();
        int min = Math.min(w, h);
        int cx = rect.getCenterX();
        int cy = rect.getCenterY();
        int r = min / 2;
        return new Rect(
                cx - r + bound,
                cy - r + bound,
                cx + r - bound,
                cy + r - bound
        );
    }

    private class CubeGridHandler extends EventHandler {

        CubeGridHandler(EventRunner runner) throws IllegalArgumentException {
            super(runner);
        }

        @Override
        protected void processEvent(InnerEvent event) {
            super.processEvent(event);
            float v = (float) event.object;
            int eventId = event.eventId;
            if (v < 0.25f) {
                v = 1 - (v * 4);
            } else if (v >= 0.25 && v <= 0.5) {
                v = (v - 0.25f) * 4;
            } else {
                v = 1f;
            }
            radius[eventId] = v;
            invalidate();
        }
    }

    private class CubeGridRunnable implements Runnable {

        private int index;
        private float v = 0;

        CubeGridRunnable(int index) {
            this.index = index;
        }

        @Override
        public void run() {
            if (v > 1) {
                v = 0;
            }
            float value = getInterpolation(v);
            handler.sendEvent(InnerEvent.get(index, value));
            v += 0.019;
        }

        private float getInterpolation(float t) {
            return t;
        }
    }
}
